package com.example.batch.core.monitor;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Histogram;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 详细的指标收集器,继承自基础指标收集器,提供更细粒度的监控
 */
@Slf4j
@Component
public class DetailedMetricsCollector extends MetricsCollector {

    // SQL类型执行时间统计,key为dataSource:sqlType
    private final Map<String, Timer> sqlTypeTimers = new ConcurrentHashMap<>();
    
    // 慢查询计数器,key为dataSource:sqlType
    private final Map<String, Counter> slowQueryCounters = new ConcurrentHashMap<>();
    
    // 结果集大小分布统计,key为dataSource
    private final Map<String, Histogram> resultSetSizeHistogram = new ConcurrentHashMap<>();
    
    // 慢查询阈值(毫秒)
    private final long slowQueryThreshold;
    
    // 大结果集阈值(行数)
    private final int largeResultThreshold;

    public DetailedMetricsCollector(MeterRegistry registry, 
            @Value("${spring.batch.metrics.detailed.slow-query-threshold:1000}") long slowQueryThreshold,
            @Value("${spring.batch.metrics.detailed.large-result-threshold:1000}") int largeResultThreshold) {
        super(registry);
        this.slowQueryThreshold = slowQueryThreshold;
        this.largeResultThreshold = largeResultThreshold;
    }

    /**
     * 记录SQL执行的详细指标
     * @param dataSource 数据源名称
     * @param sqlType SQL类型(SELECT/INSERT/UPDATE/DELETE)
     * @param timeMs 执行时间(毫秒)
     * @param resultSize 结果集大小
     * @param tags 额外的标签
     */
    public void recordSqlExecution(String dataSource, String sqlType, long timeMs, 
            int resultSize, Map<String, String> tags) {
        // 记录SQL类型执行时间
        getOrCreateSqlTypeTimer(dataSource, sqlType, tags)
            .record(timeMs, TimeUnit.MILLISECONDS);
            
        // 记录结果集大小分布
        if (resultSize > 0) {
            getOrCreateResultSetHistogram(dataSource)
                .record(resultSize);
        }
        
        // 记录慢查询
        if (timeMs > slowQueryThreshold) {
            getOrCreateSlowQueryCounter(dataSource, sqlType)
                .increment();
            
            log.warn("Slow query detected on {}: type={}, time={}ms, size={}", 
                dataSource, sqlType, timeMs, resultSize);
        }
    }

    /**
     * 记录事务相关指标
     * @param dataSource 数据源名称
     * @param status 事务状态
     * @param timeMs 事务执行时间
     * @param operationCount 事务中的操作数量
     */
    public void recordTransactionMetrics(String dataSource, TransactionStatus status, 
            long timeMs, int operationCount) {
        // 记录事务执行时间
        Timer.builder("transaction.duration")
            .tag("dataSource", dataSource)
            .tag("status", status.name())
            .register(registry)
            .record(timeMs, TimeUnit.MILLISECONDS);
            
        // 记录事务操作数
        Gauge.builder("transaction.operations", operationCount)
            .tag("dataSource", dataSource)
            .register(registry);
            
        // 记录事务成功/失败计数
        Counter.builder("transaction.total")
            .tag("dataSource", dataSource)
            .tag("status", status.name())
            .register(registry)
            .increment();
    }

    /**
     * 获取或创建SQL类型计时器
     */
    private Timer getOrCreateSqlTypeTimer(String dataSource, String sqlType, Map<String, String> tags) {
        String key = String.format("%s:%s", dataSource, sqlType);
        return sqlTypeTimers.computeIfAbsent(key, k -> {
            Timer.Builder builder = Timer.builder("sql.execution.time")
                .tag("dataSource", dataSource)
                .tag("type", sqlType);
                
            // 添加额外标签
            tags.forEach(builder::tag);
            
            return builder.register(registry);
        });
    }

    /**
     * 获取或创建结果集大小直方图
     */
    private Histogram getOrCreateResultSetHistogram(String dataSource) {
        return resultSetSizeHistogram.computeIfAbsent(dataSource, k ->
            Histogram.builder("sql.resultset.size")
                .tag("dataSource", dataSource)
                .register(registry));
    }

    /**
     * 获取或创建慢查询计数器
     */
    private Counter getOrCreateSlowQueryCounter(String dataSource, String sqlType) {
        String key = String.format("%s:%s", dataSource, sqlType);
        return slowQueryCounters.computeIfAbsent(key, k ->
            Counter.builder("sql.slow.query.count")
                .tag("dataSource", dataSource)
                .tag("type", sqlType)
                .register(registry));
    }

    /**
     * 获取指定数据源的慢查询比例
     */
    public double getSlowQueryRatio(String dataSource) {
        double totalQueries = getTotalQueries(dataSource);
        if (totalQueries == 0) {
            return 0.0;
        }
        return getSlowQueries(dataSource) / totalQueries;
    }

    /**
     * 获取指定数据源的总查询数
     */
    private double getTotalQueries(String dataSource) {
        return sqlTypeTimers.entrySet().stream()
            .filter(e -> e.getKey().startsWith(dataSource + ":"))
            .mapToDouble(e -> e.getValue().count())
            .sum();
    }

    /**
     * 获取指定数据源的慢查询数
     */
    private double getSlowQueries(String dataSource) {
        return slowQueryCounters.entrySet().stream()
            .filter(e -> e.getKey().startsWith(dataSource + ":"))
            .mapToDouble(e -> e.getValue().count())
            .sum();
    }
}
 